package subraSoft.centaurus.gui.option;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.netbeans.validation.api.ui.ValidationGroup;
import org.netbeans.validation.api.ui.ValidationPanel;

import subraSoft.centaurus.gui.option.amb.CenTableModel;
import subraSoft.centaurus.gui.validators.impl.CenTableSelectionValidator;
import subraSoft.centaurus.model.cobj.CenDefaultCObj;

/**
 * Estructura basica de cualquier chooser.
 * 
 * @author christian
 */
public abstract class CenChooser extends JPanel implements 
	CenIErrorDisplayer
{
	private static final long serialVersionUID = 1L;

	private ValidationPanel validationPanel;
	private JPanel panel;
	protected JTable table;
	private CenTableModel model;
	private JTextField tf;
	
	/**
	 * Constructor, crea todos los componentes genericos e invoca 
	 * la creacion de los componentes particulares de la aplicacion.
	 */
	@SuppressWarnings("unchecked")
	public CenChooser()
	{
		setLayout(new BorderLayout());
		this.validationPanel = new ValidationPanel();
		this.panel = new JPanel(new BorderLayout());
		validationPanel.setInnerComponent(panel);
		super.add(validationPanel, BorderLayout.CENTER);
		
		// NO ES MUY LINDO PARA SIMULA EL ERROR DE NO 
		// SELECCION DE LA TABLA DEL CHOOSER EN UN COMPONENTE
		// DE TEXTO
		tf = new JTextField("-1");
		tf.setName("Tabla");
		tf.setVisible(false);
		getValidationGroup().add(tf, new CenTableSelectionValidator());
		panel.add(tf, BorderLayout.NORTH);

		model = getModel();
		table = new JTable(model);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
			@Override
			public void valueChanged(ListSelectionEvent e) {
				tf.setText(Integer.toString(table.getSelectedRow()));			
			}
		});
		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.setMaximumSize(new Dimension(600, 150));
		scrollPane.setMinimumSize(new Dimension(600, 150));
		scrollPane.setPreferredSize(new Dimension(600, 150));
		panel.add(scrollPane, BorderLayout.CENTER);
	}
	
	/**
	 * Optiene el grupo de validacion del chooser, al que los componentes
	 * que deseen realizar una validacion dinamica deberian agregarse.
	 * 
	 * @return el grupo de validacion del chooser.
	 */
	public ValidationGroup getValidationGroup() {
		return validationPanel.getValidationGroup();
	}

	/**
	 * Setea la lista de valores entre los cualse se debera elegir.
	 * 
	 * @param choices la lista de valores entre los cualse se debera elegir.
	 */
	public void setChoiceList(List<CenDefaultCObj> choices)
	{
		model.setDataProvider(choices);
	}
	
	/**
	 * Obtiene el modelo particular del chooser.
	 * 
	 * @return el modelo particular del chooser.
	 */
	public abstract CenTableModel getModel();

	/**
	 * Obtiene la liste de elementos seleccionados (aunque solo sea uno).
	 * 
	 * @return la liste de elementos seleccionados (aunque solo sea uno).
	 */
	public List<CenDefaultCObj> getSelected()
	{
		List<CenDefaultCObj> list = new ArrayList<CenDefaultCObj>();
		if(table.getSelectedRow() >= 0)
		{
			CenDefaultCObj c = model.getObject(table.getSelectedRow());
			list.add(c);
			return list;
		}
		else
			return null;
	}

	/**
	 * Sobreescribir en caso de querer validar retornando el error correspondiente.
	 * Por defecto no hace nada.
	 * 
	 * @return null en caso OK, el string del error.
	 */
	public String validateChooser() 
	{
		return null;
	}
	
	// -------------------------------------------------------
	
	@Override
	public Component add(Component comp, int index) {
		throw new RuntimeException("No se pueden agegar componentes");
	}

	@Override
	public void add(Component comp, Object constraints, int index) {
		throw new RuntimeException("No se pueden agegar componentes");
	}

	@Override
	public void add(Component comp, Object constraints) {
		throw new RuntimeException("No se pueden agegar componentes");
	}

	@Override
	public Component add(Component comp) {
		throw new RuntimeException("No se pueden agegar componentes");
	}

	@Override
	public Component add(String name, Component comp) {
		throw new RuntimeException("No se pueden agegar componentes");
	}
	
	// -------------------------------------------------------
	
	// ERROR DISPLAYER
	
	@Override
	public void addChangeListener(ChangeListener cl) {
		validationPanel.addChangeListener(cl);
	}

	@Override
	public ValidationPanel getValidationPanel() {
		return validationPanel;
	}

	@Override
	public void removeChangeListener(ChangeListener cl) {
		validationPanel.removeChangeListener(cl);
	}
}